/*
 * REFThreadEvent.cpp
 *
 *  Created on: Apr 26, 2013
 *      Author: Lucifer
 */
#include "../pch.h"
#include "SyncBlock.h"
#include "REFThreadEvent.h"
#include "REFThread.h"
#include <sys/timeb.h>

namespace BFX
{

/**
 * Initializes a new instance of the BFX::REFThreadEvent class.
 * @param[in] bInitialState True to set the initial state to signaled; false to set the initial state to non-signaled.
 * @param[in] bAutoReset True indicates notifies one of wating threads; false indicates notifies all waiting threads.
 */
REFThreadEvent::REFThreadEvent(bool bInitialState, bool bAutoReset)
{
	m_lState = bInitialState ? 1 : 0;
	m_bAutoReset = bAutoReset;
}

/**
 * Blocks the current thread until the current event object receives a signal.
 * @param[in] nMillisecondsTimeout The number of milliseconds to wait, or (-1) to wait indefinitely.
 * @return True if the current instance receives a signal; otherwise, false.
 * @see BFX::ThreadInterruptException, BFX::ThreadAbortException
 */
bool REFThreadEvent::Wait(int nMillisecondsTimeout)
{
	BFX_REQUIRE1(nMillisecondsTimeout >= -1, "Timeout value must be either non-negative and less than or equal to INT_MAX or -1.");

	SyncBlock::SyncLock lock(&m_syncBlock);

	if (!m_lState)
		m_syncBlock.Wait(nMillisecondsTimeout);
	if (m_bAutoReset)
		return (Interlocked::Exchange(&m_lState, 0) != 0);
	else
		return (m_lState != 0);
}

/**
 * Sets the state of the event to signaled, allowing one or more waiting threads to proceed.
 */
void REFThreadEvent::Set()
{
	SyncBlock::SyncLock lock(&m_syncBlock);

	Interlocked::Exchange(&m_lState, 1);
	m_syncBlock.SignalAll();
}

/**
 * Sets the state of the event to non-signaled, causing threads to block.
 */
void REFThreadEvent::Reset()
{
	Interlocked::Exchange(&m_lState, 0);
}

}	//	namespace BFX
